home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / editors / eedraw / src / ed / eelibs1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-24  |  30.4 KB  |  874 lines

  1. /*****************************************************************************
  2. *   Module to handle libraries (first part - file and io).             *
  3. *                                         *
  4. * Written by:  Gershon Elber            IBM PC Ver 1.0,    Oct. 1989    *
  5. *****************************************************************************/
  6.  
  7. #include <math.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <conio.h>
  11. #include <string.h>
  12. #include <dos.h>
  13. #include <dir.h>
  14. #include <alloc.h>
  15. #include <time.h>
  16. #include "Program.h"
  17. #include "Director.h"
  18. #include "PriorQue.h"
  19. #include "EELibs.h"
  20. #include "EELibsL.h"
  21. #include "EEModify.h"
  22. #include "EERedraw.h"
  23. #include "EEString.h"
  24. #include "EELayer.h"
  25. #include "Primary.h"
  26. FILE *debug;
  27. LibraryStruct
  28.     *LibraryList = NULL;            /* All part libs are saved here. */
  29. static IntrCursorShapeStruct Cursor = {
  30.     INTR_CURSOR_ARROW, 0, 0, 0, 0, FALSE, NULL, FALSE
  31. };
  32.  
  33. static char *GetLine(FILE *f, char *Line, int *LineNum);
  34. static PriorQue *LoadLibraryAux(FILE *f, int *NumOfParts);
  35. static char *GetPinsEntry(FILE *f, char *Line, int *LineNum, int NumOfPins);
  36. static int *GetMultiEntry(FILE *f, char *Line, int *LineNum, int NumOfUnits,
  37.                             int PinsPerUnit);
  38. static LibraryDrawEntryStruct *GetDrawEntry(FILE *f, char *Line, int *LineNum,
  39.             BooleanType *HasLines, LibraryEntryStruct *LibEntry);
  40. static void UpdateBBox(LibraryEntryStruct *LibEntry, int x, int y);
  41. static void FreeLibraryEntry(LibraryEntryStruct *Entry);
  42. static LibraryStruct *FindLibrary(char *Name);
  43.  
  44. /*****************************************************************************
  45. * Routine to load a library from the current directory.                 *
  46. *****************************************************************************/
  47. void LoadLibrary(void)
  48. {
  49.     int i, NumOfFiles, NumOfParts;
  50.     char *p, LibName[FILE_NAME_LEN];
  51.     FILE *f;
  52.     FileNameType *FileNames;
  53.     LibraryStruct *NewLib;
  54.     PriorQue *Entries;
  55.  
  56.     if ((FileNames = GetFileNamesDir("*.lib", ".", &NumOfFiles)) != NULL) {
  57.     qsort(FileNames, NumOfFiles, sizeof(FileNameType),
  58.           (int (*)(const void *, const void *)) strcmp);
  59.     if ((i = IntrQueryList("Load Lib", (char **) FileNames,
  60.              sizeof(FileNameType), NumOfFiles, EEListNumDisplayed,
  61.                          EEPopUpFrameColor, EEPopUpBackColor, EEPopUpForeColor,
  62.                          EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  63.                          INTR_WNDW_PLACE_CENTER)) < 0) {
  64.         MyFree((VoidPtr) FileNames);
  65.         return;
  66.     }
  67.     strcpy(LibName, FileNames[i]);
  68.     if ((p = strchr(LibName, '.')) != NULL) p[0] = 0;
  69.     if (FindLibrary(LibName) != NULL) {
  70.         /* Library by that name already exists - kill old one? */
  71.         if (IntrQueryYesNo("Library by that name exists, overwrite?",
  72.               EEPopUpFrameColor, EEPopUpBackColor, EEPopUpForeColor,
  73.                       EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  74.                       INTR_WNDW_PLACE_CENTER)) {
  75.         FreeLibrary(LibName);
  76.         }
  77.         else {
  78.         MyFree((VoidPtr) FileNames);
  79.         return;
  80.         }
  81.     }
  82.     f = fopen(FileNames[i], "rt");
  83.     MyFree((VoidPtr) FileNames);
  84.     if (f == NULL) {
  85.         IntrQueryContinue("Failed to open library", EEPopUpFrameColor,
  86.                           EEPopUpBackColor, EEPopUpForeColor,
  87.                               EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  88.                               INTR_WNDW_PLACE_CENTER);
  89.         return;
  90.     }
  91.     if ((Entries = LoadLibraryAux(f, &NumOfParts)) != NULL) {
  92.         NewLib = (LibraryStruct *) MyMalloc(sizeof(LibraryStruct));
  93.         NewLib -> Entries = Entries;
  94.         NewLib -> NumOfParts = NumOfParts;
  95.         strcpy(NewLib -> Name, LibName);
  96.         NewLib -> Pnext = LibraryList;
  97.         LibraryList = NewLib;
  98.     }
  99.     fclose(f);
  100.     }
  101.     else {
  102.     IntrQueryContinue("No libraries found", EEPopUpFrameColor,
  103.                       EEPopUpBackColor, EEPopUpForeColor,
  104.                           EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  105.                           INTR_WNDW_PLACE_CENTER);
  106.     }
  107. }
  108.  
  109. /*****************************************************************************
  110. * Routine to load the given library name. FullLibName should hold full path  *
  111. * of file name to open, while LibName should hold only its name.         *
  112. * IF library already exists, it is NOT reloaded.                 *
  113. *****************************************************************************/
  114. void LoadLibraryName(char *FullLibName, char *LibName)
  115. {
  116.     int NumOfParts;
  117.     FILE *f;
  118.     LibraryStruct *NewLib;
  119.     PriorQue *Entries;
  120.  
  121.     if (FindLibrary(LibName) != NULL) return;
  122.  
  123.     f = fopen(FullLibName, "rt");
  124.     if (f == NULL) {
  125.     IntrQueryContinue("Failed to open library", EEPopUpFrameColor,
  126.                       EEPopUpBackColor, EEPopUpForeColor,
  127.                           EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  128.                           INTR_WNDW_PLACE_CENTER);
  129.     return;
  130.     }
  131.     if ((Entries = LoadLibraryAux(f, &NumOfParts)) != NULL) {
  132.     NewLib = (LibraryStruct *) MyMalloc(sizeof(LibraryStruct));
  133.     NewLib -> Entries = Entries;
  134.     NewLib -> NumOfParts = NumOfParts;
  135.     strcpy(NewLib -> Name, LibName);
  136.     NewLib -> Pnext = LibraryList;
  137.     LibraryList = NewLib;
  138.     }
  139.     fclose(f);
  140. }
  141.  
  142. /*****************************************************************************
  143. * Routine to load all libraries specified in LoadLibraryList which assumes   *
  144. * to hold names of libraries to load, seperated by commas and with no lib    *
  145. * extension. Note we dont use strtok as LoadLibraryName uses it internally.  *
  146. *****************************************************************************/
  147. void LoadLibraries(char *LoadLibraryList)
  148. {
  149.     char *p,*pcc, *NextLibName, Name[LINE_LEN_SHORT], Line[LINE_LEN],
  150.     *LibName = LoadLibraryList;
  151.  
  152.     if (!strtok(LibName, "\n\r") || strlen(LibName) == 0) return;
  153.  
  154.     do {
  155.     if ((NextLibName = strchr(LibName, ',')) != NULL) {
  156.         NextLibName[0] = 0;
  157.         NextLibName = &NextLibName[1];
  158.     }
  159.  
  160.     strcpy(Name, LibName);
  161.     if ((p = strrchr(Name, '.')) != NULL && strlen(p) < 5) *p = 0;
  162.     strcat(Name, ".lib");
  163.     p = searchpath(Name);
  164.     if (p != NULL) {
  165.         IntrDrawMessage(p, EEPopUpForeColor, EEPopUpBackColor);
  166.         LoadLibraryName(p, LibName);
  167.         IntrEraseMessage();
  168.     }
  169.     else { 
  170.         pcc = getenv("EEDLIB");
  171.         if(pcc==NULL){
  172.             fprintf(stderr,"EEDRAW: Libraries not found in search path, and EEDLIB not set\n");
  173.             exit(1);
  174.         }
  175.         sprintf(Line,"%s\\%s",pcc,Name);
  176.         p=Line;
  177.         IntrDrawMessage(p, EEPopUpForeColor, EEPopUpBackColor);
  178.         LoadLibraryName(p, LibName);
  179.         IntrEraseMessage();
  180.         
  181. /*
  182.             sprintf(Line, "Failed to find library \"%s\"", Name);
  183.         IntrQueryContinue(Line, EEPopUpFrameColor,
  184.                           EEPopUpBackColor, EEPopUpForeColor,
  185.                               EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  186.                               INTR_WNDW_PLACE_CENTER);
  187.         return;
  188. */
  189.     }
  190.  
  191.     LibName = NextLibName;
  192.     }
  193.     while (LibName != NULL);
  194. }
  195.  
  196. /*****************************************************************************
  197. * Routine to free a library from the current loaded libraries.             *
  198. * If LibName is NULL, the user is interactively requested for lib name.         *
  199. *****************************************************************************/
  200. void FreeLibrary(char *LibName)
  201. {
  202.     int i,
  203.     NumOfLibs = NumOfLibraries();
  204.     char **Names;
  205.     LibraryStruct *Lib, *TempLib;
  206.  
  207.     if (NumOfLibs == 0) {
  208.     IntrQueryContinue("No libraries are loaded", EEPopUpFrameColor,
  209.                       EEPopUpBackColor, EEPopUpForeColor,
  210.                           EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  211.                           INTR_WNDW_PLACE_CENTER);
  212.     return;
  213.     }
  214.     if (LibName == NULL) {        /* Need to ask for what lib to free: */
  215.     Names = (char **) MyMalloc(sizeof(char *) * NumOfLibs);
  216.     for (i = 0, Lib = LibraryList; Lib != NULL; Lib = Lib -> Pnext, i++)
  217.         Names[i] = Lib -> Name;
  218.         i = IntrQueryList("Free Lib", Names, 0, NumOfLibs,
  219.               EEListNumDisplayed, EEPopUpFrameColor,
  220.                           EEPopUpBackColor, EEPopUpForeColor,
  221.                           EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  222.                           INTR_WNDW_PLACE_CENTER);
  223.     MyFree((VoidPtr) Names);
  224.  
  225.     if (i >= 0)
  226.         for (Lib = LibraryList; i > 0; i--, Lib = Lib -> Pnext);
  227.     else
  228.         return;
  229.     }
  230.     else {                 /* Simply search for this library name: */
  231.     for (Lib = LibraryList;
  232.          Lib != NULL && strcmp(LibName, Lib -> Name) != 0;
  233.          Lib = Lib -> Pnext);
  234.     if (Lib == NULL) return;
  235.     }
  236.  
  237.     if (Lib == LibraryList)
  238.     LibraryList = Lib -> Pnext;
  239.     else {
  240.     for (TempLib = LibraryList;
  241.          TempLib -> Pnext != Lib;
  242.          TempLib = TempLib -> Pnext);
  243.     TempLib -> Pnext = TempLib -> Pnext -> Pnext;
  244.     }
  245.     PQFreeFunc(Lib -> Entries, FreeLibraryEntry);
  246.     MyFree((VoidPtr) Lib);
  247. }
  248.  
  249. /*****************************************************************************
  250. * Routine to return pointers to all library names.                 *
  251. *****************************************************************************/
  252. char **GetLibNames(void)
  253. {
  254.     int i,
  255.     NumOfLibs = NumOfLibraries();
  256.     char **Names;
  257.     LibraryStruct *Lib;
  258.  
  259.     Names = (char **) MyMalloc(sizeof(char *) * (NumOfLibs + 1));
  260.     for (i = 0, Lib = LibraryList; Lib != NULL; Lib = Lib -> Pnext, i++)
  261.     Names[i] = Lib -> Name;
  262.     Names[i] = NULL;
  263.  
  264.     return Names;
  265. }
  266.  
  267. /*****************************************************************************
  268. * Routine to read one line from given file.                     *
  269. *****************************************************************************/
  270. static char *GetLine(FILE *f, char *Line, int *LineNum)
  271. {
  272.     do {
  273.     if (fgets(Line, LINE_LEN - 1, f) == NULL) return NULL;
  274.     ++*LineNum;
  275.     }
  276.     while (Line[0] == '#' || Line[0] == '\n' || Line[0] == 0);
  277.  
  278.     return Line;
  279. }
  280.  
  281. /*****************************************************************************
  282. * Routine to compare two LibraryEntryStruct for the PriorQue module.         *
  283. * Comparison is based on Part name.                         *
  284. *****************************************************************************/
  285. int LibraryEntryCompare(LibraryEntryStruct *LE1,
  286.             LibraryEntryStruct *LE2)
  287. {
  288.     return strcmp(LE1 -> Name, LE2 -> Name);
  289. }
  290.  
  291. /*****************************************************************************
  292. * Routine to load a library from given open file.                 *
  293. *****************************************************************************/
  294. static PriorQue *LoadLibraryAux(FILE *f, int *NumOfParts)
  295. {
  296.     int LineNum = 0;
  297.     char Line[LINE_LEN_LONG], *p, *Name, *Prefix;
  298.     BooleanType Res, HasLines;
  299.     PriorQue
  300.     *PQ = NULL;
  301.     LibraryEntryStruct *LibEntry;
  302.  
  303.     *NumOfParts = 0;
  304.  
  305.     if (GetLine(f, Line, &LineNum) == NULL ||
  306.     strncmp(Line, FILE_IDENT, sizeof(FILE_IDENT) - 1) != 0) {
  307.     IntrQueryContinue("File is NOT EEDRAW library!", EEPopUpFrameColor,
  308.                   EEPopUpBackColor, EEPopUpForeColor,
  309.                           EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  310.                           INTR_WNDW_PLACE_CENTER);
  311.     return NULL;
  312.     }
  313.  
  314.     PQInit(&PQ);
  315.     PQCompFunc((PQCompFuncType) LibraryEntryCompare);
  316.  
  317.     while (GetLine(f, Line, &LineNum)) {
  318.     p = strtok(Line, " \t\n");
  319.  
  320.     if (strcmp(p, "DEF") != 0) {
  321.         sprintf(Line, "DEF command expected in line %d, aborted.",
  322.                                 LineNum);
  323.         IntrQueryContinue(Line, EEPopUpFrameColor,
  324.                       EEPopUpBackColor, EEPopUpForeColor,
  325.                           EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  326.                               INTR_WNDW_PLACE_CENTER);
  327.  
  328.         return PQ;
  329.     }
  330.     else {
  331.         /* Read one DEF/ENDDEF part entry from library: */
  332.         LibEntry = (LibraryEntryStruct *)
  333.                        MyMalloc(sizeof(LibraryEntryStruct));
  334.         LibEntry -> BBoxMinX = LibEntry -> BBoxMaxX =
  335.         LibEntry -> BBoxMinY = LibEntry -> BBoxMaxY = 0;
  336.         LibEntry -> Pins = NULL;
  337.         LibEntry -> Drawings = NULL;
  338.         LibEntry -> Multi = NULL;
  339.  
  340.         if ((Name = strtok(NULL, " \t\n")) == NULL ||      /* Part name: */
  341.         (Prefix = strtok(NULL, " \t\n")) == NULL ||  /* Prefix name: */
  342.         (p = strtok(NULL, " \t\n")) == NULL ||         /* NumOfPins: */
  343.         sscanf(p, "%d", &LibEntry -> NumOfPins) != 1 ||
  344.         (p = strtok(NULL, " \t\n")) == NULL ||        /* TextInside: */
  345.         sscanf(p, "%d", &LibEntry -> TextInside) != 1 ||
  346.         (p = strtok(NULL, " \t\n")) == NULL ||            /* DrawNums: */
  347.         sscanf(p, "%d", &LibEntry -> DrawNums) != 1 ||
  348.         (p = strtok(NULL, " \t\n")) == NULL ||        /* NumOfUnits: */
  349.         sscanf(p, "%d", &LibEntry -> NumOfUnits) != 1 ||
  350.         (LibEntry -> NumOfUnits > 0 &&
  351.          ((p = strtok(NULL, " \t\n")) == NULL ||     /* PinsPerUnit: */
  352.            sscanf(p, "%d", &LibEntry -> PinsPerUnit) != 1)) ||
  353.         strlen(Name) > PART_NAME_LEN ||
  354.         strlen(Prefix) > PREFIX_NAME_LEN) {
  355.         sprintf(Line, "Wrong DEF format in line %d, aborted.",
  356.                                 LineNum);
  357.         IntrQueryContinue(Line, EEPopUpFrameColor,
  358.                       EEPopUpBackColor, EEPopUpForeColor,
  359.                           EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  360.                               INTR_WNDW_PLACE_CENTER);
  361.         FreeLibraryEntry(LibEntry);
  362.         return PQ;
  363.         }
  364.         else {
  365.         /* Copy part name and prefix. */
  366.         strupr(Name);
  367.         if ((LibEntry -> DrawName = Name[0] != '~') != FALSE)
  368.             strcpy(LibEntry -> Name, Name);
  369.         else
  370.             strcpy(LibEntry -> Name, &Name[1]);
  371.         if (strcmp(Prefix, "~") == 0)
  372.             LibEntry -> Prefix[0] = 0;
  373.         else
  374.             strcpy(LibEntry -> Prefix, Prefix);
  375.         }
  376.  
  377.         HasLines = FALSE;
  378.         while (TRUE) {
  379.         GetLine(f, Line, &LineNum);
  380.         p = strtok(Line, " \t\n");
  381.  
  382.         Res = TRUE;
  383.         if (strcmp(p, "ENDDEF") == 0) {
  384.             ++*NumOfParts;
  385.             break;
  386.         }
  387.         else if (strcmp(p, "DRAW") == 0)
  388.             Res = (LibEntry -> Drawings =
  389.                GetDrawEntry(f, Line, &LineNum, &HasLines,
  390.                                LibEntry)) != NULL;
  391.         else if (strcmp(p, "PINS") == 0)
  392.             Res = (LibEntry -> Pins =
  393.                GetPinsEntry(f, Line, &LineNum, LibEntry -> NumOfPins))
  394.                                       != NULL;
  395.         else if (strcmp(p, "MULTI") == 0) {
  396.             if (LibEntry -> NumOfUnits > 0)
  397.             Res = (LibEntry -> Multi = GetMultiEntry(f, Line, &LineNum,
  398.                    LibEntry -> NumOfUnits, LibEntry -> PinsPerUnit))
  399.                                       != NULL;
  400.             else {
  401.             sprintf(Line, "MULTI found in DEF with #Units = 0 in line %d, aborted.",
  402.                                 LineNum);
  403.             IntrQueryContinue(Line, EEPopUpFrameColor,
  404.                       EEPopUpBackColor, EEPopUpForeColor,
  405.                           EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  406.                               INTR_WNDW_PLACE_CENTER);
  407.             FreeLibraryEntry(LibEntry);
  408.             return PQ;
  409.             }
  410.         }
  411.         else {
  412.             sprintf(Line, "Undefined command \"%s\" in line %d, aborted.",
  413.                                 p, LineNum);
  414.             IntrQueryContinue(Line, EEPopUpFrameColor,
  415.                       EEPopUpBackColor, EEPopUpForeColor,
  416.                           EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  417.                               INTR_WNDW_PLACE_CENTER);
  418.             FreeLibraryEntry(LibEntry);
  419.             return PQ;
  420.         }
  421.  
  422.         if (!Res) {              /* Something went wrong there. */
  423.             FreeLibraryEntry(LibEntry);
  424.             return PQ;
  425.         }
  426.         }
  427.         if (LibEntry -> Pins == NULL && HasLines) {
  428.         sprintf(Line, "No PINS defined for part in line %d, aborted.",
  429.                                 LineNum);
  430.         IntrQueryContinue(Line, EEPopUpFrameColor,
  431.                       EEPopUpBackColor, EEPopUpForeColor,
  432.                           EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  433.                               INTR_WNDW_PLACE_CENTER);
  434.         MyFree((VoidPtr) LibEntry);
  435.         return PQ;
  436.         }
  437.         if (LibEntry -> NumOfUnits > 0) {
  438.         if (LibEntry -> Multi == NULL) {
  439.             sprintf(Line, "No MULTI defined for part in line %d, aborted.",
  440.                                 LineNum);
  441.             IntrQueryContinue(Line, EEPopUpFrameColor,
  442.                       EEPopUpBackColor, EEPopUpForeColor,
  443.                           EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  444.                               INTR_WNDW_PLACE_CENTER);
  445.             MyFree((VoidPtr) LibEntry);
  446.             return PQ;
  447.         }
  448.         if (LibEntry -> Drawings == NULL) {
  449.             sprintf(Line, "No DRAW defined for part in line %d, aborted.",
  450.                                 LineNum);
  451.             IntrQueryContinue(Line, EEPopUpFrameColor,
  452.                       EEPopUpBackColor, EEPopUpForeColor,
  453.                           EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  454.                               INTR_WNDW_PLACE_CENTER);
  455.             MyFree((VoidPtr) LibEntry);
  456.             return PQ;
  457.         }
  458.         }
  459.         if (LibEntry -> Drawings == NULL) {
  460.         /* Initialize BBox manually - its only a box with pins: */
  461.         LibEntry -> BBoxMaxX = LibEntry -> BBoxMaxY =
  462.            PIN_WIDTH * LibEntry -> NumOfPins / 2 + PIN_LENGTH;
  463.         LibEntry -> BBoxMinX = LibEntry -> BBoxMinY =
  464.             -LibEntry -> BBoxMaxX;
  465.         }
  466.  
  467.         /* If we are here, this part is O.k. - put it in: */
  468.         PQInsert(&PQ, LibEntry);
  469.     }
  470.     }
  471.  
  472.     return PQ;
  473. }
  474.  
  475. /*****************************************************************************
  476. * Routine to load a PINS definition from given file. Note "PINS" line has    *
  477. * been read already. Reads upto and include ENDPINS, or an error (NULL ret). *
  478. *****************************************************************************/
  479. static char *GetPinsEntry(FILE *f, char *Line, int *LineNum, int NumOfPins)
  480. {
  481.     int i;
  482.     char *p, Pins[LINE_LEN_LONG];
  483.  
  484.     Pins[0] = 0;
  485.     for (i = 0; i < NumOfPins; i++) {
  486.     if (GetLine(f, Line, LineNum) == NULL) {
  487.         IntrQueryContinue("File ended prematurely", EEPopUpFrameColor,
  488.                       EEPopUpBackColor, EEPopUpForeColor,
  489.                           EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  490.                               INTR_WNDW_PLACE_CENTER);
  491.         return NULL;
  492.     }
  493.  
  494.     p = strtok(Line, "\n");             /* Remove the CR from line end. */
  495.     if (strcmp(p, "ENDPINS") == 0) {
  496.         sprintf(Line, "ENDPINS too soon (not enough pins) in line %d, aborted.", *LineNum);
  497.         IntrQueryContinue(Line, EEPopUpFrameColor,
  498.                       EEPopUpBackColor, EEPopUpForeColor,
  499.                           EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  500.                               INTR_WNDW_PLACE_CENTER);
  501.         return NULL;
  502.     }
  503.     if ((p[0] == '~' && strlen(p) == 1))           /* Empty line ("~") ? */
  504.         strcat(Pins, "~");
  505.     else
  506.         strcat(Pins, p);
  507.     strcat(Pins, PIN_SEPERATOR);
  508.     if (strlen(Pins) > LINE_LEN_LONG - 10) {
  509.         sprintf(Line, "Pin definitions are too long in line %d, aborted.",
  510.                                 *LineNum);
  511.         IntrQueryContinue(Line, EEPopUpFrameColor,
  512.                       EEPopUpBackColor, EEPopUpForeColor,
  513.                           EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  514.                               INTR_WNDW_PLACE_CENTER);
  515.         return NULL;
  516.     }
  517.     }
  518.  
  519.     if (GetLine(f, Line, LineNum) == NULL) {
  520.     IntrQueryContinue("File ended prematurely", EEPopUpFrameColor,
  521.                   EEPopUpBackColor, EEPopUpForeColor,
  522.                       EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  523.                           INTR_WNDW_PLACE_CENTER);
  524.     return NULL;
  525.     }
  526.     p = strtok(Line, " \t\n");
  527.     if (strcmp(p, "ENDPINS") != 0) {
  528.     sprintf(Line, "ENDPINS expected in line %d, aborted.", *LineNum);
  529.     IntrQueryContinue(Line, EEPopUpFrameColor,
  530.                   EEPopUpBackColor, EEPopUpForeColor,
  531.                       EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  532.                           INTR_WNDW_PLACE_CENTER);
  533.     return NULL;
  534.     }
  535.  
  536.     return strdup(Pins);
  537. }
  538.  
  539. /*****************************************************************************
  540. * Routine to load a MULTI definition from given file. Note "MULTI" line has  *
  541. * been read already. Reads upto and include ENDMULTI, or an error (NULL ret).*
  542. *****************************************************************************/
  543. static int *GetMultiEntry(FILE *f, char *Line, int *LineNum, int NumOfUnits,
  544.                             int PinsPerUnit)
  545. {
  546.     int i, j, *Array,
  547.     Count = 0;
  548.     char *p;
  549.  
  550.     Array = (int *) MyMalloc(sizeof(int) * NumOfUnits * PinsPerUnit);
  551.  
  552.     for (i = 0; i < NumOfUnits; i++) {
  553.     if (GetLine(f, Line, LineNum) == NULL) {
  554.         IntrQueryContinue("File ended prematurely", EEPopUpFrameColor,
  555.                       EEPopUpBackColor, EEPopUpForeColor,
  556.                           EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  557.                               INTR_WNDW_PLACE_CENTER);
  558.         MyFree((VoidPtr) Array);
  559.         return NULL;
  560.     }
  561.  
  562.     for (p = strtok(Line, " \t\n"), j = 0;
  563.          j < PinsPerUnit;
  564.          p = strtok(NULL, " \t\n"), j++) {
  565.         if (p == NULL ||
  566.         sscanf(p, "%d", &Array[Count++]) != 1) {
  567.         sprintf(Line, "MULTI has less pins than needed in line %d",
  568.                                 *LineNum);
  569.         IntrQueryContinue(Line, EEPopUpFrameColor,
  570.                           EEPopUpBackColor, EEPopUpForeColor,
  571.                               EEPopUpXorColor, EEWindowsFrameWidth,
  572.                                   &Cursor, INTR_WNDW_PLACE_CENTER);
  573.         MyFree((VoidPtr) Array);
  574.         return NULL;
  575.         }
  576.     }
  577.     }
  578.  
  579.     if (GetLine(f, Line, LineNum) == NULL) {
  580.     IntrQueryContinue("File ended prematurely", EEPopUpFrameColor,
  581.                   EEPopUpBackColor, EEPopUpForeColor,
  582.                       EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  583.                           INTR_WNDW_PLACE_CENTER);
  584.     return NULL;
  585.     }
  586.     p = strtok(Line, " \t\n");
  587.     if (strcmp(p, "ENDMULTI") != 0) {
  588.     sprintf(Line, "ENDMULTI expected in line %d, aborted.", *LineNum);
  589.     IntrQueryContinue(Line, EEPopUpFrameColor,
  590.                   EEPopUpBackColor, EEPopUpForeColor,
  591.                       EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  592.                           INTR_WNDW_PLACE_CENTER);
  593.     return NULL;
  594.     }
  595.  
  596.     return Array;
  597. }
  598.  
  599. /*****************************************************************************
  600. * Routine to load a DRAW definition from given file. Note "DRAW" line has    *
  601. * been read already. Reads upto and include ENDDRAW, or an error (NULL ret). *
  602. *****************************************************************************/
  603. static LibraryDrawEntryStruct *GetDrawEntry(FILE *f, char *Line, int *LineNum,
  604.             BooleanType *HasLines, LibraryEntryStruct *LibEntry)
  605. {
  606.     int i;
  607.     char *p, Buffer[LINE_LEN_SHORT];
  608.     RealType r;
  609.     BooleanType
  610.     Error = FALSE;
  611.     LibraryDrawEntryStruct *Tail, *New,
  612.     *Head = NULL;
  613.  
  614.     *HasLines = FALSE;
  615.  
  616.     while (TRUE) {
  617.     if (GetLine(f, Line, LineNum) == NULL) {
  618.         IntrQueryContinue("File ended prematurely", EEPopUpFrameColor,
  619.                       EEPopUpBackColor, EEPopUpForeColor,
  620.                           EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  621.                               INTR_WNDW_PLACE_CENTER);
  622.         return Head;
  623.     }
  624.  
  625.     if (strncmp(Line, "ENDDRAW", 7) == 0) break;
  626.  
  627.     New = (LibraryDrawEntryStruct *)
  628.                    MyMalloc(sizeof(LibraryDrawEntryStruct));
  629.     New -> Pnext = NULL;
  630.  
  631.     switch (Line[0]) {
  632.         case 'A': /* Arc */
  633.         New -> DrawType = ARC_DRAW_TYPE;
  634.         Error = sscanf(&Line[2], "%d %d %d %d %d %d",
  635.             &New -> Layer,
  636.             &New -> U.Arc.x, &New -> U.Arc.y, &New -> U.Arc.r,
  637.             &New -> U.Arc.t1, &New -> U.Arc.t2) != 6;
  638.         New ->U.Arc.x *= LIB_SCALE_DRAW;
  639.         New ->U.Arc.y *= LIB_SCALE_DRAW;
  640.         New ->U.Arc.r *= LIB_SCALE_DRAW;
  641.         NORMALIZE_ANGLE(New -> U.Arc.t1);
  642.         NORMALIZE_ANGLE(New -> U.Arc.t2);
  643.         if (New -> U.Arc.t1 > New -> U.Arc.t2)
  644.             New -> U.Arc.t2 += 360;
  645.         New -> U.Arc.t1 += 1; /* Force arc of 180 degree to be less. */
  646.         New -> U.Arc.t2 -= 1;
  647.  
  648.         /* Update the bbox: */
  649.         UpdateBBox(LibEntry, New -> U.Arc.x - New -> U.Arc.r,
  650.                      New -> U.Arc.y - New -> U.Arc.r);
  651.         UpdateBBox(LibEntry, New -> U.Arc.x + New -> U.Arc.r,
  652.                      New -> U.Arc.y + New -> U.Arc.r);
  653.         break;
  654.         case 'C': /* Circle */
  655.         New -> DrawType = CIRCLE_DRAW_TYPE;
  656.         Error = sscanf(&Line[2], "%d %d %d %d",
  657.             &New -> Layer,
  658.             &New -> U.Circ.x, &New -> U.Circ.y, &New -> U.Circ.r) != 4;
  659.         New ->U.Circ.x *= LIB_SCALE_DRAW;
  660.         New ->U.Circ.y *= LIB_SCALE_DRAW;
  661.         New ->U.Circ.r *= LIB_SCALE_DRAW;
  662.         /* Update the bbox: */
  663.         UpdateBBox(LibEntry, New -> U.Circ.x - New -> U.Circ.r,
  664.                      New -> U.Circ.y - New -> U.Circ.r);
  665.         UpdateBBox(LibEntry, New -> U.Circ.x + New -> U.Circ.r,
  666.                      New -> U.Circ.y + New -> U.Circ.r);
  667.         break;
  668.         case 'T': /* Text */
  669.         New -> DrawType = TEXT_DRAW_TYPE;
  670.         Error = sscanf(&Line[2], "%d %d %d %d %s",
  671.                    &New -> Layer,
  672.                    &New -> U.Text.x, &New -> U.Text.y,
  673.                    &New -> U.Text.Horiz, Buffer) != 5;
  674.         if (!Error) {               /* Convert '~' to spaces. */
  675.             for (i = 0; i < strlen(Buffer); i++)
  676.             if (Buffer[i] == '~') Buffer[i] = ' ';
  677.             New -> U.Text.Text = strdup(Buffer);
  678.         }
  679.         New ->U.Text.x *= LIB_SCALE_DRAW;
  680.         New ->U.Text.y *= LIB_SCALE_DRAW;
  681.         break;
  682.         case 'S': /* Square */
  683.         New -> DrawType = SQUARE_DRAW_TYPE;
  684.         Error = sscanf(&Line[2], "%d %d %d %d %d",
  685.                    &New -> Layer,
  686.                    &New -> U.Sqr.x1, &New -> U.Sqr.y1,
  687.                    &New -> U.Sqr.x2, &New -> U.Sqr.y2) != 5;
  688.         New ->U.Sqr.x1 *= LIB_SCALE_DRAW;
  689.         New ->U.Sqr.y1 *= LIB_SCALE_DRAW;
  690.         New ->U.Sqr.x2 *= LIB_SCALE_DRAW;
  691.         New ->U.Sqr.y2 *= LIB_SCALE_DRAW;
  692.         break;
  693.         case 'L': /* Line */
  694.         *HasLines = TRUE;
  695.         New -> DrawType = LINE_DRAW_TYPE;
  696.         if ((i = sscanf(&Line[2], "%d %d %d %d %d %s",
  697.                 &New -> Layer,
  698.                 &New -> U.Line.x1, &New -> U.Line.y1,
  699.                 &New -> U.Line.x2, &New -> U.Line.y2,
  700.                 Buffer)) != 6)
  701.             i = sscanf(&Line[2], "%d %d %d %d %d",
  702.                    &New -> Layer,
  703.                    &New -> U.Line.x1, &New -> U.Line.y1,
  704.                    &New -> U.Line.x2, &New -> U.Line.y2);
  705.         Error = (i != 5 && i != 6) ||
  706.             (New -> U.Line.x1 != New -> U.Line.x2 &&
  707.              New -> U.Line.y1 != New -> U.Line.y2);
  708.         New ->U.Line.x1 *= LIB_SCALE_DRAW;
  709.         New ->U.Line.y1 *= LIB_SCALE_DRAW;
  710.         New ->U.Line.x2 *= LIB_SCALE_DRAW;
  711.         New ->U.Line.y2 *= LIB_SCALE_DRAW;
  712.         UpdateBBox(LibEntry, New -> U.Line.x1, New -> U.Line.y1);
  713.         UpdateBBox(LibEntry, New -> U.Line.x2, New -> U.Line.y2);
  714.         New -> U.Line.Invert = i == 5 && Buffer[0] == 'I';
  715.         break;
  716.         case 'P': /* Polyline */
  717.  
  718.         New -> DrawType = POLYLINE_DRAW_TYPE;
  719.         New -> U.Poly.PolyList = NULL;
  720.  
  721.          p = strtok(&Line[4], " \t\n"); 
  722.  
  723.  
  724.  
  725.         if (sscanf(/*p*/&Line[2], "%d %d",
  726.              &New -> Layer, &New -> U.Poly.n) == 2 &&
  727.             New -> U.Poly.n > 0) {
  728.             New -> U.Poly.PolyList = (int *)
  729.             MyMalloc(sizeof(int) * New -> U.Poly.n * 2);
  730.         
  731.             for (i = 0; i < New -> U.Poly.n * 2 && !Error; i++) {
  732.             p = strtok(NULL, " \t\n");
  733.             Error = sscanf(p, "%d", &New -> U.Poly.PolyList[i]) !=
  734.                                     1;
  735.             New ->U.Poly.PolyList[i] *= LIB_SCALE_DRAW;
  736.             if (i % 2 != 0)
  737.                 UpdateBBox(LibEntry, New -> U.Poly.PolyList[i-1],
  738.                          New -> U.Poly.PolyList[i]);
  739.             }
  740.             New -> U.Poly.Fill = (p = strtok(NULL, " \t\n")) != NULL &&
  741.                      p[0] == 'F';
  742.         }
  743.         else
  744.             Error = TRUE;
  745.         Error |= New -> U.Poly.Fill &&
  746.             (New -> U.Poly.PolyList[0] != New -> U.Poly.PolyList[i-2] ||
  747.              New -> U.Poly.PolyList[1] != New -> U.Poly.PolyList[i-1]);
  748.         if (Error && New -> U.Poly.PolyList)
  749.             MyFree((VoidPtr) New -> U.Poly.PolyList);
  750.         break;
  751.         default:
  752.         sprintf(Line, "Undefined DRAW command in line %d, aborted.",
  753.                                 *LineNum);
  754.         IntrQueryContinue(Line, EEPopUpFrameColor,
  755.                           EEPopUpBackColor, EEPopUpForeColor,
  756.                               EEPopUpXorColor, EEWindowsFrameWidth,
  757.                                   &Cursor, INTR_WNDW_PLACE_CENTER);
  758.         return Head;
  759.     }
  760.     if (Error) {
  761.         sprintf(Line, "Error in %c DRAW command in line %d, aborted.",
  762.                             Line[0], *LineNum);
  763.         IntrQueryContinue(Line, EEPopUpFrameColor,
  764.                       EEPopUpBackColor, EEPopUpForeColor,
  765.                           EEPopUpXorColor, EEWindowsFrameWidth,
  766.                               &Cursor, INTR_WNDW_PLACE_CENTER);
  767.         MyFree((VoidPtr) New);
  768.         /* FLush till end of draw: */
  769.         do {
  770.         if (GetLine(f, Line, LineNum) == NULL) {
  771.             IntrQueryContinue("File ended prematurely",
  772.                                       EEPopUpFrameColor, EEPopUpBackColor,
  773.                                       EEPopUpForeColor, EEPopUpXorColor,
  774.                                       EEWindowsFrameWidth, &Cursor,
  775.                                       INTR_WNDW_PLACE_CENTER);
  776.             return Head;
  777.         }
  778.         }
  779.         while (strncmp(Line, "ENDDRAW", 7) != 0);
  780.         return Head;
  781.     }
  782.     else {
  783.         if (Head == NULL)
  784.         Head = Tail = New;
  785.         else {
  786.         Tail -> Pnext = New;
  787.         Tail = New;
  788.         }
  789.     }
  790.     }
  791.  
  792.     /* Update the bbox to the maximum extrem as we may rotate the object. */
  793.     r = MAX(ABS(LibEntry->BBoxMinX), ABS(LibEntry->BBoxMaxX));
  794.     r = MAX(r, ABS(LibEntry->BBoxMinY));
  795.     r = MAX(r, ABS(LibEntry->BBoxMaxY));
  796.     LibEntry->BBoxMaxX = LibEntry->BBoxMaxY = r;
  797.     LibEntry->BBoxMinX = LibEntry->BBoxMinY = -r;
  798.  
  799.     return Head;
  800. }
  801.  
  802. /*****************************************************************************
  803. * Routine to update LibEntry bounding box accrding to given x, y value.         *
  804. *****************************************************************************/
  805. static void UpdateBBox(LibraryEntryStruct *LibEntry, int x, int y)
  806. {
  807.     if (LibEntry -> BBoxMinX > x) LibEntry -> BBoxMinX = x;
  808.     if (LibEntry -> BBoxMaxX < x) LibEntry -> BBoxMaxX = x;
  809.     if (LibEntry -> BBoxMinY > y) LibEntry -> BBoxMinY = y;
  810.     if (LibEntry -> BBoxMaxY < y) LibEntry -> BBoxMaxY = y;
  811. }
  812.  
  813. /*****************************************************************************
  814. * Routine to free one library entry.                         *
  815. *****************************************************************************/
  816. static void FreeLibraryEntry(LibraryEntryStruct *Entry)
  817. {
  818.     LibraryDrawEntryStruct *TempDraw,
  819.     *Drawings = Entry -> Drawings;
  820.  
  821.     if (Entry -> Pins) MyFree((VoidPtr) Entry -> Pins);
  822.     if (Entry -> Multi) MyFree((VoidPtr) Entry -> Multi);
  823.     while (Drawings) {
  824.     TempDraw = Drawings;
  825.     Drawings = Drawings -> Pnext;
  826.  
  827.     switch (TempDraw -> DrawType) {
  828.         case ARC_DRAW_TYPE:
  829.         case CIRCLE_DRAW_TYPE:
  830.         case SQUARE_DRAW_TYPE:
  831.         case LINE_DRAW_TYPE:
  832.         break;
  833.         case TEXT_DRAW_TYPE:
  834.         MyFree((VoidPtr) TempDraw -> U.Text.Text);
  835.         break;
  836.         case POLYLINE_DRAW_TYPE:
  837.         MyFree((VoidPtr) TempDraw -> U.Poly.PolyList);
  838.         break;
  839.     }
  840.     MyFree((VoidPtr) TempDraw);
  841.     }
  842.  
  843.     MyFree((VoidPtr) Entry);
  844. }
  845.  
  846. /*****************************************************************************
  847. * Routine to find the library given its name.                     *
  848. *****************************************************************************/
  849. static LibraryStruct *FindLibrary(char *Name)
  850. {
  851.     LibraryStruct
  852.     *Lib = LibraryList;
  853.  
  854.     while (Lib) {
  855.     if (strcmp(Name, Lib -> Name) == 0) return Lib;
  856.     Lib = Lib -> Pnext;
  857.     }
  858.     return NULL;
  859. }
  860.  
  861. /*****************************************************************************
  862. * Routine to find the number of libraries currently loaded.             *
  863. *****************************************************************************/
  864. int NumOfLibraries(void)
  865. {
  866.     int i;
  867.     LibraryStruct
  868.     *Lib = LibraryList;
  869.  
  870.     for (i = 0; Lib != NULL; Lib = Lib -> Pnext) i++;
  871.  
  872.     return i;
  873. }
  874.